home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 3
/
Cream of the Crop 3.iso
/
comm
/
wnos5src.zip
/
IFACE.C
< prev
next >
Wrap
Text File
|
1993-08-09
|
11KB
|
523 lines
#include <stdio.h>
#include "global.h"
#include "config.h"
#include "mbuf.h"
#include "proc.h"
#include "iface.h"
#include "ip.h"
#include "netuser.h"
#include "ax25.h"
#include "enet.h"
#include "pktdrvr.h"
#include "cmdparse.h"
#include "commands.h"
/* Loopback pseudo-interface */
struct iface Loopback = {
&Encap, /* Link to next entry */
"loopback", /* name */
CL_NONE, /* type */
&Iftypes[0], /* iftype */
0x7f000001L, /* addr 127.0.0.1 */
0xffffffffL, /* broadcast 255.255.255.255 */
0xffffffffL, /* netmask 255.255.255.255 */
NULL, /* (*ioctl) */
NULLFP, /* (*send) */
NULLFP, /* (*output) */
NULLFP, /* (*raw) */
NULLFP, /* (*stop) */
NULLFP, /* (*status) */
MAXINT16, /* mtu No limit */
0, /* dev */
0, /* xdev */
0, /* port */
0, /* trace */
NULLCHAR, /* trfile */
NULLFILE, /* trfp */
NULLCHAR, /* hwaddr */
NULLIF, /* forw */
0, /* ipsndcnt */
0, /* rawsndcnt */
0, /* iprcvcnt */
0, /* rawrcvcnt */
0, /* lastsent */
0, /* lastrecv */
NULLPROC, /* rxproc */
NULLPROC, /* txproc */
NULLPROC, /* supv */
NULL, /* extension */
0,
NULLLQ,
MAXDEFAULT,
0,
};
/* Encapsulation pseudo-interface */
struct iface Encap = {
NULLIF,
"encap", /* name */
CL_NONE, /* type */
&Iftypes[0], /* iftype */
INADDR_ANY, /* addr 0.0.0.0 */
0xffffffffL, /* broadcast 255.255.255.255 */
0xffffffffL, /* netmask 255.255.255.255 */
NULL, /* (*ioctl) */
ip_encap, /* (*send) */
NULLFP, /* (*output) */
NULLFP, /* (*raw) */
NULLFP, /* (*stop) */
NULLFP, /* (*status) */
MAXINT16, /* mtu No limit */
0, /* dev */
0, /* xdev */
0, /* port */
0, /* trace */
NULLCHAR, /* trfile */
NULLFILE, /* trfp */
NULLCHAR, /* hwaddr */
NULLIF, /* forw */
0, /* ipsndcnt */
0, /* rawsndcnt */
0, /* iprcvcnt */
0, /* rawrcvcnt */
0, /* lastsent */
0, /* lastrecv */
NULLPROC, /* rxproc */
NULLPROC, /* txproc */
NULLPROC, /* supv */
NULL, /* extension */
0,
NULLLQ,
MAXDEFAULT,
0,
};
/* Interface list header */
struct iface *Ifaces = &Loopback;
char Badif[] = "Interface %s unknown\n";
char Badax[] = "Interface %s not AX25\n";
char Badasy[] = "Interface %s not ASY port\n";
char Noipaddr[] = "IP adress not set\n";
char Ifexist[] = "Interface %s already exists\n";
#ifdef AX25
void
init_flags(struct iface *ifp)
{
ifp->flags = mxallocw(sizeof(struct flags));
ifp->flags->maxframe = Maxframe;
ifp->flags->t1init = T1init;
ifp->flags->t2init = T2init;
ifp->flags->t3init = T3init;
ifp->flags->t4init = T4init;
ifp->flags->t5init = T5init;
ifp->flags->retries = Retries;
ifp->flags->axwindow = Axwindow;
ifp->flags->paclen = Paclen;
ifp->flags->pthresh = Pthresh;
ifp->flags->digipeat = Digipeat;
ifp->flags->t3disc = T3disc;
}
#endif
/* Given a network mask, return the number of contiguous 1-bits starting
* from the most significant bit.
*/
static int near
mask2width(int32 mask)
{
int i, width = 0;
for(i = 31; i >= 0; i--) {
if(!(mask & (1 << i))) {
break;
}
width++;
}
return width;
}
/* Set interface IP address */
static int
ifipaddr(int argc,char **argv,void *p)
{
struct iface *ifp = p;
int32 addr;
if((addr = resolve(argv[1])) == 0) {
tprintf(Badhost,argv[1]);
return -1;
}
ifp->addr = addr;
return 0;
}
/* Set link (hardware) address */
static int
iflinkadr(int argc,char **argv,void *p)
{
struct iface *ifp = p;
if(ifp->iftype == NULLIFT || ifp->iftype->scan == NULL) {
tputs("Can't set link address\n");
return -1;
}
if(*ifp->iftype->scan != 0) {
if(ifp->hwaddr != NULLCHAR) {
xfree(ifp->hwaddr);
}
ifp->hwaddr = mxallocw(ifp->iftype->hwalen);
return (*ifp->iftype->scan)(ifp->hwaddr,argv[1]);
}
return 0;
}
/* Set interface broadcast address. This is actually done
* by installing a private entry in the routing table.
*/
static int
ifbroad(int argc,char **argv,void *p)
{
struct iface *ifp = p;
struct route *rp;
if((rp = rt_blookup(ifp->broadcast,32)) != NULLROUTE && rp->iface == ifp) {
rt_drop(ifp->broadcast,32);
}
if((ifp->broadcast = resolve(argv[1])) == 0) {
tprintf(Badhost,argv[1]);
return -1;
}
rt_add(ifp->broadcast,32,0,ifp,1,0,1);
return 0;
}
static int
ifname(int argc,char **argv,void *p)
{
struct iface *ifp = p;
if(ifp->name != NULLCHAR) {
xfree(ifp->name);
}
ifp->name = strxdup(argv[1]);
return 0;
}
/* Set the network mask. This is actually done by installing
* a routing entry.
*/
static int
ifnetmsk(int argc,char **argv,void *p)
{
struct iface *ifp = p;
struct route *rp;
/* Remove old entry if it exists */
if((rp = rt_blookup(ifp->addr & ifp->netmask,mask2width(ifp->netmask))) != NULLROUTE) {
rt_drop(rp->target,rp->bits);
}
ifp->netmask = htol(argv[1]);
rt_add(ifp->addr,mask2width(ifp->netmask),0,ifp,0,0,0);
return 0;
}
/* Command to set interface encapsulation mode */
static int
ifencap(int argc,char **argv,void *p)
{
struct iface *ifp = p;
if(setencap(ifp,argv[1]) != 0) {
tprintf("Encap mode %s unknown\n",argv[1]);
return 1;
}
return 0;
}
/* Function to set encapsulation mode */
int
setencap(struct iface *ifp,char *mode)
{
struct iftype *ift;
for(ift = &Iftypes[0];ift->name != NULLCHAR;ift++) {
if(strnicmp(ift->name,mode,strlen(mode)) == 0) {
break;
}
}
if(ift->name == NULLCHAR) {
return -1;
}
ifp->iftype = ift;
ifp->send = ift->send;
ifp->output = ift->output;
ifp->type = ift->type;
return 0;
}
#ifdef XXX
/* Set interface receive buffer size */
static int
ifrxbuf(int argc,char **argv,void *p)
{
return 0; /* To be written */
}
#endif
/* Set interface Maximum Transmission Unit */
static int
ifmtu(int argc,char **argv,void *p)
{
struct iface *ifp = p;
ifp->mtu = atoi(argv[1]);
return 0;
}
/* Set interface forwarding */
static int
ifforw(int argc,char **argv,void *p)
{
struct iface *ifp = p;
if((ifp->forw = if_lookup(argv[1])) == NULLIF) {
return -1;
}
if(ifp->forw == ifp) {
ifp->forw = NULLIF;
}
return 0;
}
/* Display the parameters for a specified interface */
static void near
showiface(struct iface *ifp)
{
char tmp[25];
tprintf("%-10s IP addr %s MTU %u Link encap ",
ifp->name,inet_ntoa(ifp->addr),ifp->mtu);
if(ifp->iftype == NULLIFT) {
tputs("not set\n");
} else {
tprintf("%s\n",ifp->iftype->name);
if(ifp->iftype->format != NULL && ifp->hwaddr != NULLCHAR) {
tprintf("%20s %s\n",
"Link addr",(*ifp->iftype->format)(tmp,ifp->hwaddr));
}
}
tprintf("%16s 0x%x netmask 0x%08lx\n",
"trace",ifp->trace,ifp->netmask);
tprintf("%19s %lu tot %lu idle %s\n",
"sent: ip",ifp->ipsndcnt,ifp->rawsndcnt,tformat(secclock() - ifp->lastsent));
tprintf("%19s %lu tot %lu idle %s\n",
"recv: ip",ifp->iprecvcnt,ifp->rawrecvcnt,tformat(secclock() - ifp->lastrecv));
if(ifp->forw != NULLIF) {
tprintf("%28s %s\n","output forward to",ifp->forw->name);
}
}
/* Command to detach an interface */
int
dodetach(int argc,char **argv,void *p)
{
struct iface *ifp;
if((ifp = if_lookup(argv[1])) == NULLIF){
tprintf(Badif,argv[1]);
return 1;
}
if(if_detach(ifp) == -1) {
tputs("Can't detach loopback interface\n");
}
return 0;
}
/* Detach a specified interface */
int
if_detach(struct iface *ifp)
{
struct iface *iftmp;
struct route *rp, *rptmp = NULLROUTE;
if(ifp == &Loopback || ifp == &Encap) {
return -1;
}
/* Drop all routes that point to this interface */
if(R_default.iface == ifp) {
rt_drop(0,0); /* Drop default route */
}
for(rp = Routes; rp != NULLROUTE; rp = rptmp) {
rptmp = rp->next;
if(rp->iface == ifp) {
rt_drop(rp->target,rp->bits);
}
}
/* Unforward any other interfaces forwarding to this one */
for(iftmp = Ifaces; iftmp != NULLIF; iftmp = iftmp->next) {
if(iftmp->forw == ifp) {
iftmp->forw = NULLIF;
}
}
/* Call device shutdown routine, if any */
if(ifp->stop != NULLFP) {
(*ifp->stop)(ifp,0);
}
killproc(ifp->proc);
killproc(ifp->proc1);
killproc(ifp->supv);
/* Free allocated memory associated with this interface */
if(ifp->name != NULLCHAR) {
xfree(ifp->name);
}
if(ifp->hwaddr != NULLCHAR) {
xfree(ifp->hwaddr);
}
/* Remove from interface list */
if(ifp == Ifaces) {
Ifaces = ifp->next;
} else {
/* Search for entry just before this one
* (necessary because list is only singly-linked.)
*/
for(iftmp = Ifaces; iftmp != NULLIF; iftmp = iftmp->next) {
if(iftmp->next == ifp) {
break;
}
}
if(iftmp != NULLIF && iftmp->next == ifp) {
iftmp->next = ifp->next;
}
}
if(ifp->lq != NULLLQ) {
xfree(ifp->lq);
}
/* Finally free the structure itself */
xfree(ifp);
return 0;
}
/* Given the ascii name of an interface, return a pointer to the structure,
* or NULLIF if it doesn't exist
*/
struct iface *
if_lookup(char *name)
{
struct iface *ifp;
for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next) {
if(strcmp(ifp->name,name) == 0) {
return ifp;
}
}
return NULLIF;
}
struct iface *
cmp_if(char *ifname)
{
struct iface *ifp;
if((ifp = if_lookup(ifname)) == NULLIF) {
tprintf(Badif,ifname);
return NULLIF;
}
if(ifp->output != ax_output) {
tprintf(Badax,ifname);
return NULLIF;
}
return ifp;
}
/* Return iface pointer if 'addr' belongs to one of our interfaces,
* NULLIF otherwise.
* This is used to tell if an incoming IP datagram is for us, or if it
* has to be routed.
*/
struct iface *
ismyaddr(int32 addr)
{
struct iface *ifp;
for(ifp = Ifaces; ifp != NULLIF; ifp = ifp->next) {
if(addr == ifp->addr) {
return ifp;
}
}
return NULLIF;
}
/* return buffer with name + comment */
char *
if_name(struct iface *ifp,char *comment)
{
char *result = mxallocw(strlen(ifp->name) + strlen(comment) + 2);
sprintf(result,"%s%s",ifp->name,comment);
return result;
}
#ifdef ASY
/* Raw output routine that tosses all packets. Used by dialer, tip, etc */
int
bitbucket(struct iface *ifp,struct mbuf *bp)
{
free_p(bp);
return 0;
}
#endif
/* Set interface parameters */
int
doifconfig(int argc,char **argv,void *p)
{
struct iface *ifp;
int i;
struct cmds Ifcmds[] = {
"broadcast", ifbroad, 0, 2, NULLCHAR,
"encapsulation", ifencap, 0, 2, NULLCHAR,
"forward", ifforw, 0, 2, NULLCHAR,
"ipaddress", ifipaddr, 0, 2, NULLCHAR,
"linkaddress", iflinkadr, 0, 2, NULLCHAR,
"mtu", ifmtu, 0, 2, NULLCHAR,
"name", ifname, 0, 2, NULLCHAR,
"netmask", ifnetmsk, 0, 2, NULLCHAR,
#ifdef XXX
"rxbuf", ifrxbuf, 0, 2, NULLCHAR,
#endif
NULLCHAR,
};
if(argc < 2) {
for(ifp = Ifaces;ifp != NULLIF;ifp = ifp->next) {
showiface(ifp);
}
return 0;
}
if((ifp = if_lookup(argv[1])) == NULLIF) {
tprintf(Badif,argv[1]);
return -1;
}
if(argc == 2) {
showiface(ifp);
if(ifp->status != NULLFP) {
(*ifp->status)(ifp);
}
return 0;
}
if(argc == 3) {
tputs("Argument missing\n");
return -1;
}
for(i = 2; i < argc - 1; i += 2) {
subcmd(Ifcmds,3,&argv[i-1],ifp);
}
return 0;
}